export function parser(file, tokens) {
  let token = null;
  const next = () => {
    token = tokens.next().value;
    console.log("parser: ", token && token.type);
  };

  const NumbericLiteral = () => {
    if (token.type === "NumbericLiteral") {
      const _token = token;
      next();
      return _token;
    }
  };

  //#region *
  const MulToken = () => {
    if (token.type === "MulToken") {
      const _token = token;
      next();
      return _token;
    }

    return null;
  };

  const MulExpression = (left) => {
    const op = MulToken() || DivToken();
    if (!op) return left;
    const right = NumbericLiteral();
    if (!right) {
      throw new SyntaxError(
        `Expected token type "NumbericLiteral" got "${token.type}" at 
          ${file}:${token.loc.start.line}:${token.loc.start.column}`
      );
    }

    const node = {
      type: "BinaryExpression",
      left,
      operatorToken: op,
      right,
      // TODO: loc
    };

    return MulExpression(node);
  };
  //#endregion

  //#region /
  const DivToken = () => {
    if (token.type === "DivToken") {
      const _token = token;
      next();
      return _token;
    }

    return null;
  };
  //#endregion

  //#region +
  const PlusToken = () => {
    if (token.type === "PlusToken") {
      const _token = token;
      next();
      return _token;
    }

    return null;
  };

  const PlusExpression = (left) => {
    const op = PlusToken();
    if (!op) return left;
    const next = NumbericLiteral();
    if (!next) {
      throw new SyntaxError(
        `Expected token type "NumbericLiteral" got "${token.type}" at 
          ${file}:${token.loc.start.line}:${token.loc.start.column}`
      );
    }

    const right = MulExpression(next);
    const node = {
      type: "BinaryExpression",
      left,
      operatorToken: op,
      right,
      // TODO: loc
    };

    return PlusExpression(node);
  };
  //#endregion

  const BinaryExpression = () => {
    const head = NumbericLiteral();
    if (!head) return null;

    return PlusExpression(MulExpression(head)); // 这里可以处理 括号啥的的传递处理
  };

  next();
  const program = BinaryExpression();

  if (token.type !== "EndOfFileToken") {
    throw new SyntaxError(
      `Expected token type "EndOfFileToken" got "${token.type}" at 
        ${file}:${token.loc.start.line}:${token.loc.start.column}`
    );
  }

  return program;
}
